//---------------------------------------------------------------------------
// Process Class
// Author : Woo-Hyun Kim
// Email : woorung@icu.ac.kr
// Date : Jul. 7, 2006
//---------------------------------------------------------------------------
#ifndef CProcessH
#define CProcessH

#include <iostream>
#include <iterator>
#include <vector>
#include <list>
#include <algorithm>
#include <fstream>
#include <string>
#include <map>

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>

#include "sync/CSync.h"
//#include "CSyncSignal.h"
#include "log/CLog.h"

// read buf size
#define READ_BUF_SIZE 1024

#define CHILD_PROC_1 0 // 1st child process before run
#define CHILD_PROC_2 1 // 2nd child process after run

using namespace std;
//---------------------------------------------------------------------------
class CProcess {
private :
	// process execution status
	int status;

	pid_t worker_pid;

	pid_t pid;
	pid_t ppid;

	// only vaild in parent process
	pid_t cpid[2];

	// for tracing
	int verbose;
	CLog *err_log;

	// for synchronization
	CSync *master_sync;
	CSync *filter_sync;
	CSync *worker_sync;

	// child
	virtual void before_run();
	// child
	virtual void run();
	// parent
	virtual void after_run();

	virtual int input_filter();
	virtual int real_worker();
	virtual int advisor();

	void _start();
	int _waits();

protected :
	// for pipe
	int up_pipefd[2]; // for tunneling stdout 
	int down_pipefd[2]; // for tunneling stdin
	int err_pipefd[2]; //for tunneling stderr

public :
	CProcess();
	CProcess(int verbose);
	//CProcess(const CProcess &rhs);
	~CProcess();

	//virtual CProcess &operator=(const CProcess &rhs);

	pid_t get_wpid(); // worker pid forked by master
	pid_t get_pid(); 
	pid_t get_ppid();
	pid_t get_cpid(int i);

	int get_status();

	// ------------------------------------------------
	// it must be overridden in subclasses
	// ------------------------------------------------
	virtual int read_upstream(const char *buf);
	virtual int read_downstream(const char *buf);
	virtual int read_errstream(const char *buf);
	virtual int read_upstream(const void *buf, size_t size);
	virtual int read_downstream(const void *buf, size_t size);
	virtual int read_errstream(const void *buf, size_t size);
	// ------------------------------------------------

	size_t write_downstream(const char *buf);
	size_t write_upstream(const char *buf);
	size_t write_errstream(const char *buf);
	size_t write_downstream(const void *buf, size_t size);
	size_t write_upstream(const void *buf, size_t size);
	size_t write_errstream(const void *buf, size_t size);

	int close_downstream();
	int close_upstream();
	int close_errstream();

	void start();
	int waits();
};
//---------------------------------------------------------------------------
#endif
